*&---------------------------------------------------------------------*
*& Report ZEX_LISTING_43                                               *
*&---------------------------------------------------------------------*
*& Created By: James Wood (james.wood@bowdarkconsulting.com)           *
*& Created On: 12/12/2008                                              *
*& Purpose:    This program demonstrates the use of constructors for   *
*&             guaranteeing the proper initialization of encapsulated  *
*&             objects.                                                *
*&---------------------------------------------------------------------*
REPORT zex_listing_43.

*----------------------------------------------------------------------*
*       CLASS lcl_account DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_account DEFINITION.

  TYPE-POOLS: abap.

  PUBLIC SECTION.
    METHODS:
      constructor IMPORTING im_account_no
                       TYPE string,
      get_balance RETURNING value(re_balance)
                       TYPE bapicurr_d,
      deposit     IMPORTING im_amount
                       TYPE bapicurr_d,
      withdrawal  IMPORTING im_amount
                       TYPE bapicurr_d
                  RETURNING value(re_result)
                       TYPE abap_bool.

  PRIVATE SECTION.
    DATA: account_no TYPE string,
          balance    TYPE bapicurr_d.

ENDCLASS.                    "lcl_account DEFINITION

*----------------------------------------------------------------------*
*       CLASS lcl_account IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_account IMPLEMENTATION.
  METHOD constructor.
*   Query database tables to retrieve account details:
*   SELECT FROM ...
*    WHERE account_no = im_account_no.

    IF sy-subrc EQ 0.
      me->account_no = im_account_no.
      me->balance    = '0.00'.         "From database...
    ELSE.
      "Exception handling code...
    ENDIF.
  ENDMETHOD.                    "constructor

  METHOD get_balance.
    re_balance = balance.
  ENDMETHOD.                    "get_balance

  METHOD deposit.
    balance = balance + im_amount.
  ENDMETHOD.                    "deposit

  METHOD withdrawal.
    IF im_amount LE balance.
      balance = balance - im_amount.
      re_result = abap_true.
    ELSE.
      re_result = abap_false.
    ENDIF.
  ENDMETHOD.                    "withdrawal
ENDCLASS.                    "lcl_account IMPLEMENTATION

*----------------------------------------------------------------------*
* START-OF-SELECTION Event Module                                      *
*----------------------------------------------------------------------*
START-OF-SELECTION.
  PERFORM test_account.

*&---------------------------------------------------------------------*
*&      Form  test_account
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
FORM test_account.

* Local Data Declarations:
  DATA: lr_account TYPE REF TO lcl_account.

* Create a new account object; If the provided account number is
* valid, the object will be initialized using the values stored in
* the database. Otherwise, an exception (normally) would occur as the
* state of the object could not be determined. See Chapter 8 to learn
* more about exceptions with classes.
  CREATE OBJECT lr_account
    EXPORTING
      im_account_no = '1234567890'.

* Deposit $100.00 into the account. Obviously, a real-world transaction
* would scrutinize this much more deeply:
  lr_account->deposit( '100.00' ).

* Try to withdraw $250.00 from the account. Since we know that the
* account only has $100.00 in it, we know that the operation will
* fail.
  IF lr_account->withdrawal( '250.00' ) EQ abap_true.
    WRITE: / 'Withdrawal operation was successful.'.
  ELSE.
    WRITE: / 'Withdrawal operation failed - insufficient funds.'.
  ENDIF.

* Try to artificially inflate the balance to $1,000,000 dollars. In
* this case, the balance attribute is hidden, so it cannot be tampered
* with externally. Consequently, the account's balance is initialized
* in the constructor and can only be modified through controlled
* withdrawal or deposit operations:
  "lr_account->balance = '1000000.00'.

ENDFORM.                    "test_account